﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SafeLoad.NControl
{
  /// <summary>
  /// NActiveLine.xaml 的交互逻辑
  /// </summary>
  public partial class NActiveLine : UserControl
  {
    public NActiveLine()
    {
      InitializeComponent();
      offectAnimation = new DoubleAnimation(0,-10, TimeSpan.FromMilliseconds(1000));
      offectAnimation.RepeatBehavior = RepeatBehavior.Forever;
      BeginAnimation(LineOffsetProperty, offectAnimation);
    }

    private DoubleAnimation offectAnimation = null;

    public static readonly DependencyProperty LinePointsProperty =
      DependencyProperty.Register("LinePoints", typeof(string),
      typeof(NActiveLine), new PropertyMetadata("",
      new PropertyChangedCallback(RenderUpdateByPropertyChanged)));
    public string LinePoints
    {
      get { return (string)GetValue(LinePointsProperty); }
      set { SetValue(LinePointsProperty, value); }
    }

    public static readonly DependencyProperty LineWidthProperty =
      DependencyProperty.Register("LineWidth", typeof(double),
        typeof(NActiveLine), new PropertyMetadata(5d,
          new PropertyChangedCallback(RenderUpdateByPropertyChanged)));
    public double LineWidth
    {
      get { return (double)GetValue(LineWidthProperty); }
      set { SetValue(LineWidthProperty, value); }
    }

    public static readonly DependencyProperty LineActiveProperty =
      DependencyProperty.Register("LineActive", typeof(bool), typeof(NActiveLine), new PropertyMetadata(false));
    public bool LineActive
    {
      get { return (bool)GetValue(LineActiveProperty); }
      set { SetValue(LineActiveProperty, value); }
    }

    public static readonly DependencyProperty LineOffsetProperty =
      DependencyProperty.Register("LineOffset", typeof(double), typeof(NActiveLine), new PropertyMetadata(0d));
    public double LineOffset
    {
      get { return (double)GetValue(LineOffsetProperty); }
      set { SetValue(LineOffsetProperty, value); }
    }

    public static readonly DependencyProperty LineSpeedProperty =
      DependencyProperty.Register("LineSpeed", typeof(double), typeof(NActiveLine), 
        new PropertyMetadata(0d, new PropertyChangedCallback(SpeedChangedCallback)));
    public double LineSpeed
    {
      get { return (double)GetValue(LineSpeedProperty); }
      set { SetValue(LineSpeedProperty, value); }
    }

    public static void SpeedChangedCallback(DependencyObject dependency, DependencyPropertyChangedEventArgs e)
    {
      NActiveLine activeLine = (NActiveLine)dependency;
      activeLine.UpdateSpeed();
    }

    public static void RenderUpdateByPropertyChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs e)
    {
      if (dependency is NActiveLine curve)
      {
        curve.UpdateCanvas();
      }
    }

    private void UpdateCanvas()
    {
      List<Point> pointList = GetPointList();
      
      StreamGeometry pathGeo = new StreamGeometry();
      using(StreamGeometryContext context = pathGeo.Open())
      {
        if (pointList.Count > 0)
        {
          context.BeginFigure(pointList[0], false, false);
        }
        for (int i = 1; i < pointList.Count; i++)
        {
          context.LineTo(pointList[i], true, false);
        }
      }
      linePath.Data = pathGeo;


      //List<Point> pointList = GetPointList();
      //for (int i = 1; i < pointList.Count; i++)
      //{
      //  Point p1 = pointList[i - 1];
      //  Point p2 = pointList[i];

      //  double bgOffset = i > 1 ? halfWidth : 0;
      //  double edOffset = (i == pointList.Count - 1) ? 0 : halfWidth;

      //  if (Math.Abs(p1.X - p2.X) < 0.01)
      //  {
      //    Rectangle rectangle = new Rectangle();
      //    rectangle.Width = LineWidth;
      //    rectangle.Height = Math.Abs(p1.Y - p2.Y) - (bgOffset + edOffset);
      //    rectangle.Fill = verticalBrush;
      //    mainCanvas.Children.Add(rectangle);
      //    Canvas.SetLeft(rectangle, p1.X - halfWidth);
      //    if (p2.Y > p1.Y)
      //    {
      //      Canvas.SetTop(rectangle, Math.Min(p1.Y, p2.Y) + bgOffset);
      //    }
      //    else
      //    {
      //      Canvas.SetTop(rectangle, Math.Min(p1.Y, p2.Y) + edOffset);
      //    }
      //  }
      //  else
      //  {
      //    //水平
      //    Rectangle rectangle = new Rectangle();
      //    rectangle.Width = Math.Abs(p1.X - p2.X) - (bgOffset + edOffset);
      //    rectangle.Height = LineWidth;
      //    rectangle.Fill = horizontalBrush;
      //    mainCanvas.Children.Add(rectangle);
      //    if (p2.X > p1.X)
      //    {
      //      Canvas.SetLeft(rectangle, Math.Min(p1.X, p2.X) + bgOffset);
      //    }
      //    else
      //    {
      //      Canvas.SetLeft(rectangle, Math.Min(p1.X, p2.X) + edOffset);
      //    }
      //    Canvas.SetTop(rectangle, p1.Y - LineWidth / 2);
      //  }

      //  if (i >= 2)
      //  {
      //    //判断是否需要画弯
      //    Point p0 = pointList[i - 2];
      //    //中心点时p1
      //    //弯点
      //    if (Math.Abs(p2.Y - p1.Y) < 1)
      //    {
      //      p0 = pointList[i];
      //      p2 = pointList[i - 2];
      //    }
      //    //转换成 横，竖 形式
      //    Path path = new Path();
      //    string pathStr = "";
      //    RadialGradientBrush rgBrush = new RadialGradientBrush();
      //    if (p0.X < p1.X)
      //    {
      //      if (p1.Y < p2.Y)
      //      {
      //        // 右下
      //        pathStr = $"M 0,0 A {LineWidth},{LineWidth} 0 0 1 {LineWidth},{LineWidth} L 0,{LineWidth} Z";
      //        rgBrush.GradientOrigin = new Point(0, 1);
      //        rgBrush.Center = new Point(0, 1);
      //      }
      //      else
      //      {
      //        //右上
      //        pathStr = $"M {LineWidth},0 A {LineWidth},{LineWidth} 0 0 1 0,{LineWidth} L 0,0 Z";
      //        rgBrush.GradientOrigin = new Point(0, 0);
      //        rgBrush.Center = new Point(0, 0);
      //      }
      //    }
      //    else
      //    {
      //      if (p1.Y < p2.Y)
      //      {
      //        // 左下
      //        pathStr = $"M {LineWidth},0 A {LineWidth},{LineWidth} 0 0 0 0,{LineWidth} L {LineWidth},{LineWidth} Z";
      //        rgBrush.GradientOrigin = new Point(1, 1);
      //        rgBrush.Center = new Point(1, 1);
      //      }
      //      else
      //      {
      //        //左上
      //        pathStr = $"M 0,0 A {LineWidth},{LineWidth} 0 0 0 {LineWidth},{LineWidth} L {LineWidth},0 Z";
      //        rgBrush.GradientOrigin = new Point(1, 0);
      //        rgBrush.Center = new Point(1, 0);
      //      }
      //    }

      //    path.Data = (Geometry)TypeDescriptor.GetConverter(typeof(Geometry)).ConvertFrom(pathStr);
      //    rgBrush.RadiusX = 1;
      //    rgBrush.RadiusY = 1;
      //    rgBrush.GradientStops.Add(new GradientStop(Colors.DimGray, 0d));
      //    rgBrush.GradientStops.Add(new GradientStop(Colors.LightGray, 0.5d));
      //    rgBrush.GradientStops.Add(new GradientStop(Colors.DimGray, 1d));
      //    path.Fill = rgBrush;

      //    mainCanvas.Children.Add(path);

      //  }
      //}
    }

    private void UpdateSpeed()
    {
      if (LineSpeed > 0)
      {
        offectAnimation.From = 0d;
        offectAnimation.To = -10d;
        offectAnimation.Duration = TimeSpan.FromMilliseconds(300 / Math.Abs(LineSpeed));
        offectAnimation.RepeatBehavior = RepeatBehavior.Forever;
        BeginAnimation(LineOffsetProperty, offectAnimation);
      }
      else if (LineSpeed < 0)
      {
        offectAnimation.From = 0d;
        offectAnimation.To = 10d;
        offectAnimation.Duration = TimeSpan.FromMilliseconds(300 / Math.Abs(LineSpeed));
        offectAnimation.RepeatBehavior = RepeatBehavior.Forever;
        BeginAnimation(LineOffsetProperty, offectAnimation);
      }
      else
      {
        offectAnimation.From = 0d;
        offectAnimation.To = 0d;
        offectAnimation.Duration = TimeSpan.FromMilliseconds(300);
        BeginAnimation(LineOffsetProperty, offectAnimation);
      }
    }

    private List<Point> GetPointList()
    {
      string[] points = LinePoints.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
      List<Point> pointList = new List<Point>();
      foreach (string p in points)
      {
        string[] xy = p.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
        if (xy.Length == 2)
        {
          pointList.Add(new Point() { X = double.Parse(xy[0]), Y = double.Parse(xy[1]) });
        }
      }
      return pointList;
    }
  }
}
